using System;
using Net.Event;
using Net.Share;
using Net.System;
using Net.Helper;

namespace Net.Serialize
{
    /// <summary>
    /// 网络转换核心 2019.7.16
    /// </summary>
    public class NetConvert : NetConvertBase
    {
        /// <summary>
        /// 新版网络序列化
        /// </summary>
        /// <param name="model">函数名</param>
        /// <param name="flag"></param>
        /// <param name="recordType"></param>
        /// <returns></returns>
        public static byte[] Serialize(IRpcModel model, byte[] flag = null, bool recordType = false)
        {
            var segment = BufferPool.Take();
            Serialize(segment, model, flag, recordType);
            return segment.ToArray(true);
        }

        public static bool Serialize(ISegment segment, IRpcModel model, byte[] flag = null, bool recordType = false)
        {
            try
            {
                if (flag != null) segment.Write(flag, 0, flag.Length);
                segment.Write(model.Protocol);
                segment.Write(model.Pars.Length);
                foreach (object value in model.Pars)
                {
                    Type type;
                    if (value == null)
                    {
                        type = typeof(DBNull);
                        segment.Write(AssemblyHelper.GetHashType(type));
                        continue;
                    }
                    type = value.GetType();
                    segment.Write(AssemblyHelper.GetHashType(type));
                    NetConvertBinary.WriteObject(segment, type, value, recordType);
                }
                return true;
            }
            catch (Exception ex)
            {
                var func = RPCExtensions.GetFunc(model.Protocol);
                NDebug.LogError($"序列化:{func}出错,如果提示为索引溢出,你可以在Call或者Response方法直接设置serialize参数为true 详情:{ex}");
                return false;
            }
        }

        /// <summary>
        /// 新版反序列化
        /// </summary>
        /// <param name="segment"></param>
        /// <param name="model"></param>
        /// <param name="recordType"></param>
        public static bool Deserialize(ISegment segment, IRpcModel model, bool recordType = false)
        {
            try
            {
                model.Protocol = segment.ReadUInt32();
                var count = segment.ReadInt32();
                model.Pars = new object[count];
                for (int i = 0; i < count; i++)
                {
                    var typeHash = segment.ReadUInt32();
                    var type = AssemblyHelper.GetHashType(typeHash);
                    if (type == null)
                        throw new Exception($"找不到哈希类型:{typeHash}");
                    if (type == typeof(DBNull))
                        continue;
                    model.Pars[i] = NetConvertBinary.ReadObject(segment, type, recordType);
                }
                return true;
            }
            catch (Exception ex)
            {
                var func = RPCExtensions.GetFunc(model.Protocol);
                NDebug.LogError($"反序列化:{func}出错:{ex}");
                return false;
            }
        }
    }
}